package com.linkoog.devtools.intellij.ui;

import com.intellij.openapi.Disposable;
import com.intellij.openapi.ui.LoadingDecorator;
import com.intellij.ui.components.JBLoadingPanelListener;
import org.jetbrains.annotations.Nls;

import javax.swing.*;
import java.awt.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Function;

public class JBLoadingPanel extends JPanel {
    private JPanel contentPanel;
    private LoadingDecorator decorator;
    private CopyOnWriteArrayList<JBLoadingPanelListener> listeners;

    public JBLoadingPanel(LayoutManager manager, Function<JPanel, LoadingDecorator> createLoadingDecorator) {
        super(new BorderLayout());
        contentPanel = manager != null ? new JPanel(manager) : new JPanel();
        contentPanel.setOpaque(false);
        contentPanel.setFocusable(false);
        decorator = createLoadingDecorator.apply(contentPanel);
        listeners = new CopyOnWriteArrayList<>();

        add(decorator.getComponent(), BorderLayout.CENTER);
    }

    public JBLoadingPanel(LayoutManager manager, Disposable parent) {
        this(manager, panel -> new LoadingDecorator(panel, parent, -1));
    }

    public JBLoadingPanel(LayoutManager manager, Disposable parent, int startDelayMs) {
        this(manager, panel -> new LoadingDecorator(panel, parent, startDelayMs));
    }

    @Override
    public void setLayout(LayoutManager layoutManager) {
        if (!(layoutManager instanceof BorderLayout)) {
            throw new IllegalArgumentException(layoutManager.toString());
        }
        super.setLayout(layoutManager);
        if (decorator != null) {
            super.add(decorator.getComponent(), BorderLayout.CENTER);
        }
    }

    public void setLoadingText(@Nls String text) {
        decorator.setLoadingText(text);
    }

    public String getLoadingText() {
        return decorator.getLoadingText();
    }

    public void stopLoading() {
        decorator.stopLoading();
        for (JBLoadingPanelListener listener : listeners) {
            listener.onLoadingFinish();
        }
    }

    public boolean isLoading() {
        return decorator.isLoading();
    }

    public void startLoading() {
        decorator.startLoading(false);
        for (JBLoadingPanelListener listener : listeners) {
            listener.onLoadingStart();
        }
    }

    public void addListener(JBLoadingPanelListener listener) {
        listeners.add(listener);
    }

    public boolean removeListener(JBLoadingPanelListener listener) {
        return listeners.remove(listener);
    }

    @Override
    public Component add(Component comp) {
        return contentPanel.add(comp);
    }

    @Override
    public Component add(Component comp, int index) {
        return contentPanel.add(comp, index);
    }

    @Override
    public void add(Component comp, Object constraints) {
        contentPanel.add(comp, constraints);
    }

    @Override
    public Dimension getPreferredSize() {
        return contentPanel.getPreferredSize();
    }
}
